#include <iostream>
#include <set>
#include <utility>
#include <string>

using std::cout;
using std::endl;
using std::set;
using std::pair;
using std::string;

void test(){

    //set<key> a;
    //1、只能存放一种类型key，且元素是唯一的
    //2、默认情况按照key值升序排列
    //3、不支持下标访问
    set<int> number={1,3,9,7,5,3};

    //auto让编译器自动得出，it的类型是 set<int>::iterator it，即迭代器类型
    for(auto it=number.begin(); it!=number.end(); ++it){
        //cout<<&it<<endl;
        //对于迭代器 it，它的地址在整个循环过程中是不变的。
        //it 是一个迭代器对象，它的地址在内存中是固定的，不会因为 ++it 操作而改变。
        //当你在循环中使用 &it 输出迭代器 it 的地址时，
        //实际上输出的是 it 对象本身的地址，而不是迭代器所指向的元素的地址。
        
        //迭代器的移动是通过 ++it 操作来实现的，
        //它会让迭代器指向容器中的下一个元素，但并不会改变迭代器对象本身的地址。
        
        //此外，set不能通过*it=100进行赋值
        //set不支持number[0]下标访问运算符，所以只能使用迭代器遍历
    
        //cout<<&(*it)<<endl;
        //set是一种关联式容器，它内部的元素是按照特定的排序规则进行组织的，
        //通常是通过红黑树（Red-Black Tree）来实现的。
        //在红黑树中，元素的存储顺序是由其键值决定的，而不是按照在容器中的插入顺序来确定的。
        //因此，当使用&(*it)来获取元素地址时，得到的地址并不一定是规律的，
        //因为这些地址是根据元素的键值在红黑树中的存储位置决定的，
        //而不是按照元素在容器中的顺序来确定的。
        
        //cout<<it<<endl;   //不能这么输出
        
        cout<<*it<<" ";
    }

    cout<<endl;

    //count，查找元素个数，有就1，没有就0
    cout<<number.count(5)<<endl;
    cout<<number.count(15)<<endl;
    
    //find，查找某元素的位置，返回类型是迭代器
    set<int>::iterator it=number.find(7);   
    if(it == number.end())
        cout<<"不存在该元素"<<endl;
    else
        cout<<"set中有该元素"<<*it<<endl;

    cout<<endl;

    //插入insert，返回类型是pair(一种结构体)，包括iterator和bool，插入成功bool为1
    pair<set<int>::iterator,bool>ret= number.insert(8);
    if(ret.second){
        cout<<"插入成功"<<*ret.first<<endl;
    }
    else{
        cout<<"插入失败，因为该元素已经存在于set中"<<endl;
    }


    for(auto it=number.begin(); it!=number.end(); ++it){
        cout<<*it<<" ";
    }
    cout<<endl;
}


int main()
{   
    test();
    return 0;
}

